package com.yundin.aspect;

import com.yundin.annotation.AutoFill;
import com.yundin.constant.AutoFillConstant;
import com.yundin.context.BaseContext;
import com.yundin.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * 自定义切面，实现公共字段自动填充处理逻辑
 */
@Aspect
@Component//自动扫描
@Slf4j
public class AutoFillAspect {
    /**
     * 切入点
     */
    @Pointcut("execution(* com.yundin.mapper.*.*(..)) && @annotation(com.yundin.annotation.AutoFill)")
            public void autoFillPointCut(){

    }
/**
 * 前置通知，在通知中进行公共字段的赋值
*/
            @Before("autoFillPointCut()")//前置通知，方法
            public void autoFill(JoinPoint joinPoint){
/////////////////////重要////////////////////////////////////
//可先进行调试，是否能进入该方法 提前在mapper方法添加AutoFill注解
        log.info("开始进行公共字段自动填充...");
//获取到当前被拦截的方法上的数据库操作类型
                MethodSignature signature = (MethodSignature)
                        joinPoint.getSignature();//方法签名对象
                AutoFill autoFill =
                        signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解对象
                OperationType operationType = autoFill.value();//获得数据库操作类型
//获取到当前被拦截的方法的参数--实体对象
                Object[] args = joinPoint.getArgs();
                if(args == null || args.length == 0){
                    return;
                }
                Object entity = args[0];
//准备赋值的数据
                LocalDateTime now = LocalDateTime.now();
                Long currentId = BaseContext.getCurrentId();
//根据当前不同的操作类型，为对应的属性通过反射来赋值
                if(operationType == OperationType.INSERT){
//为4个公共字段赋值
                    try {
                        Method setCreateTime =
                                entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME,
                                        LocalDateTime.class);
                        Method setCreateUser =
                                entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER,
                                        Long.class);
                        Method setUpdateTime =
                                entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME,
                                        LocalDateTime.class);
                        Method setUpdateUser =
                                entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER,
                                        Long.class);
//通过反射为对象属性赋值
                        setCreateTime.invoke(entity,now);
                        setCreateUser.invoke(entity,currentId);
                        setUpdateTime.invoke(entity,now);
                        setUpdateUser.invoke(entity,currentId);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }else if(operationType == OperationType.UPDATE){
//为2个公共字段赋值
                    try {
                        Method setUpdateTime =
                                entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME,
                                        LocalDateTime.class);
                        Method setUpdateUser =
                                entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER,
                                        Long.class);
//通过反射为对象属性赋值
                        setUpdateTime.invoke(entity,now);
                        setUpdateUser.invoke(entity,currentId);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
}